package edu.ubb.remeye.util.jaxb;

import java.io.File;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import org.xml.sax.SAXException;

import edu.ubb.remeye.exception.SettingsLoadingException;
import edu.ubb.remeye.exception.SettingsSavingException;
import edu.ubb.remeye.gui.internationalization.LanguageManager;

/**
 * JAXB binder class.
 * 
 * @author Andrew Ianicicau
 *
 */
public class JAXBBinder {

	///////////////////////////////////////////////////////////////////////////////////
	////		ATTRIBUTES - JAXBBinders
	///////////////////////////////////////////////////////////////////////////////////

	/**
	 * JAXB generated classes for server settings.
	 */
	private static final String serverXMLBindings = "edu.ubb.remeye.server.settings.jaxb";
	
	/**
	 * JAXB generated classes for client settings.
	 */
	private static final String clientXMLBindings = "edu.ubb.remeye.client.settings.jaxb";
	
	/**
	 * Server XSD schema for XML generation and validation.
	 */
	private static final String serverXSD = "settings/schema/ServerSettingsSchema.xsd";
	
	/**
	 * Client XSD schema for XML generation and validation.
	 */
	private static final String clientXSD = "settings/schema/ClientSettingsSchema.xsd";
	
	/**
	 * Server XML settings file.
	 */
	private static final String serverXML = "settings/ServerSettings.xml";
	
	/**
	 * Client XML settings file.
	 */
	private static final String clientXML = "settings/ClientSettings.xml";

	
	
	///////////////////////////////////////////////////////////////////////////////////
	////		METHODS - JAXBBinder
	///////////////////////////////////////////////////////////////////////////////////
	
	/**
	 * Returns settings stored in XML file.
	 * @param server True for getting server settings, false for getting client settings.
	 * @throws SettingsLoadingException 
	 */
	public static Object loadSettings(boolean server) throws SettingsLoadingException {
		Object settings = null;
		JAXBContext context;
		File schemaFile;
		File xmlFile;

		try {
			if(server) {
				context = JAXBContext.newInstance(serverXMLBindings);
				schemaFile = new File(serverXSD);
				xmlFile = new File(serverXML);
			} else {
				context = JAXBContext.newInstance(clientXMLBindings);
				schemaFile = new File(clientXSD);
				xmlFile = new File(clientXML);
			}
			
			SchemaFactory schemaFactory = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
			Schema schema = schemaFactory.newSchema(schemaFile);
			Unmarshaller unmarshaller = context.createUnmarshaller();
			unmarshaller.setSchema(schema);
			
			settings = unmarshaller.unmarshal(xmlFile);
		} catch(JAXBException e) {
			String errorMessage = LanguageManager.getLanguageManager().getText("settingsloaderror");
			throw new SettingsLoadingException(errorMessage);
		} catch (SAXException e) {
			String errorMessage = LanguageManager.getLanguageManager().getText("settingsloaderror");
			throw new SettingsLoadingException(errorMessage);
		}
	
		return settings;
	}
	
	/**
	 * Saves settings to XML file.
	 * @param settings The JAXB generated XML binding class.
	 * @param server True for saving server settings, false for saving client settings.
	 * @throws SettingsSavingException 
	 */
	public static void saveSettings(Object settings, boolean server) throws SettingsSavingException {
		JAXBContext context;
		File schemaFile;
		File xmlFile;
		try {
			if(server) {
				context = JAXBContext.newInstance(serverXMLBindings);
				schemaFile = new File(serverXSD);
				xmlFile = new File(serverXML);
			} else {
				context = JAXBContext.newInstance(clientXMLBindings);
				schemaFile = new File(clientXSD);
				xmlFile = new File(clientXML);
			}
			
			SchemaFactory schemaFactory = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
			Schema schema = schemaFactory.newSchema(schemaFile);
			Marshaller marshaller = context.createMarshaller();
			marshaller.setSchema(schema);
			marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
			
			marshaller.marshal(settings, xmlFile);
		} catch(JAXBException e) {
			String errorMessage = LanguageManager.getLanguageManager().getText("settingssaveerror");
			throw new SettingsSavingException(errorMessage);
		} catch (SAXException e) {
			String errorMessage = LanguageManager.getLanguageManager().getText("settingssaveerror");
			throw new SettingsSavingException(errorMessage);
		}

	}

}
